package com.sansec.core.executor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.*;

/** 密码服务平台线程池
 * @author lichangwei
 */
@Slf4j
public class CryptoExecutorPool implements Executor{

    /**
     * 创建
     */
    private volatile boolean RUNNING = true;

    private boolean shutdown = false;


    /**
     * 运行线程数
     */
    private int runPoolSize=0;

    /**
     * 核心线程数
     */
    private int corePoolSize;

    /**
     * 最大线程数
     */
    private int  maximumPoolSize;

    /**
     * 任务队列（线程安全的阻塞队列）
     */
    private BlockingQueue<Runnable> workQueue;

    /**
     * 非核心线程的空闲时间
     */
    private Long keepAliveTime;

    /**
     * 线程工厂
     */
    private ThreadFactory threadFactory;

    /**
     * 拒绝策略
     */
    private RejectedExecutionHandler handler;


    private final HashSet<Thread> workers = new HashSet<>();

    private final List<Thread> threadList = new ArrayList<>();

    public String getInfo(){
        return "workQueue.size="+workQueue.size()+";workers.size="+workers.size()+";";
    }

    /** 获取默认队列
     * @return
     */
    private BlockingQueue<Runnable> getDefaultBlockingQueue(){
        return new LinkedBlockingQueue<>(50);
    }

    /** 获取默认线程工厂
     * @return
     */
    private ThreadFactory getDefaultThreadFactory(){
        return new CustomizableThreadFactory("CryptoExecutorPool-");
    }

    /** 获取默认拒绝策略
     * @return
     */
    private RejectedExecutionHandler getDefaultRejectedExecutionHandler(){
        RejectedExecutionHandler defaultRejectedExecutionHandler= (r, executor) -> {
            throw new RejectedExecutionException("Task " + r.toString() +
                    " rejected from " +
                    executor.toString());
        };
        return defaultRejectedExecutionHandler;
    }


    private void initWorks(){
        while (runPoolSize<corePoolSize){
            WorkerThread r=new WorkerThread();
            Thread thread = threadFactory.newThread(r);
            thread.start();
            workers.add(thread);
            runPoolSize++;
        }
    }


    /**
     * 创建线程池
     */
    public CryptoExecutorPool(){
        log.info("实例化线程池开始");
        this.corePoolSize = 10;
        this.maximumPoolSize = 20;
        this.workQueue = this.getDefaultBlockingQueue();
        this.keepAliveTime = TimeUnit.MILLISECONDS.toNanos(20);
        this.threadFactory = this.getDefaultThreadFactory();
        this.handler = this.getDefaultRejectedExecutionHandler();
        this.initWorks();
        log.info("实例化线程池结束");
    }


    /** 创建线程池
     * @param corePoolSize 核心线程数
     * @param maximumPoolSize 最大线程数
     * @param keepAliveTime 非核心线程的空闲时间
     * @param unit 空闲时间的单位
     */
    public CryptoExecutorPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit)
    {
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = this.getDefaultBlockingQueue();
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = this.getDefaultThreadFactory();
        this.handler = this.getDefaultRejectedExecutionHandler();
        this.initWorks();
    }



    /** 创建线程池
     * @param corePoolSize 核心线程数
     * @param maximumPoolSize 最大线程数
     * @param keepAliveTime 非核心线程的空闲时间
     * @param unit 空闲时间的单位
     * @param workQueue 任务队列（线程安全的阻塞队列）
     * @param threadFactory 线程工厂
     * @param handler 拒绝策略
     */
    public CryptoExecutorPool(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
    {
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
        this.initWorks();
    }

    @Override
    public void execute(Runnable r) {
        log.info("execute start ...");
        if (r == null){
            throw new NullPointerException();
        }
        try {
            this.workQueue.put(r);
        }
        catch (InterruptedException e) {
            log.error("execute error ",e);
        }
        log.info("execute end ...");
    }

    /**
     * 工作线程负责消费任务，并执行任务
     */
    class WorkerThread extends Thread{
        @Override
        public void run() {
            //循环取任务并执行
            while(true){
                try{
                    log.info("WorkerThread "+this.getId()+" run start ...");
                    workQueue.take().run();
                    log.info("WorkerThread "+this.getId()+" run end ...");
                }catch(InterruptedException e) {
                    log.error("WorkerThread "+this.getId()+" run error ",e);
                }
            }
        }
    }
}
